package com.mjk.common.tools.encrypt;



import com.mjk.common.base.error.BizException;
import com.mjk.common.tools.logger.BizLogger;

import java.io.*;
import java.nio.charset.StandardCharsets;

public class Base64 {
	private Base64(){}
	public static String encode(String str) {
		byte[] bytes = str.getBytes();
		return encode(bytes);
	}

	public static String encode(String str, String charset) {
		byte[] bytes;
		try {
			bytes = str.getBytes(charset);
		} catch (UnsupportedEncodingException e) {
			throw new BizException("Unsupported charset: " + charset, e);
		}
		return encode(bytes);
	}

	public static byte[] decode(String str)  {
		byte[] bytes;
		bytes = str.getBytes(StandardCharsets.US_ASCII);

		return decode(bytes);

	}

	public static String decode(String str, String charset) {
		byte[] bytes;
		bytes = str.getBytes(StandardCharsets.US_ASCII);

		byte[] decoded = decode(bytes);
		try {
			return new String(decoded, charset);
		} catch (UnsupportedEncodingException e) {
			throw new BizException("Unsupported charset: " + charset, e);
		}
	}

	public static String encode(byte[] bytes)  {
		return encode(bytes, 0);
	}

	public static String encode(byte[] bytes, int wrapAt) {
		try(
				ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
				ByteArrayOutputStream outputStream = new ByteArrayOutputStream()
        ) {
			encode(inputStream, outputStream, wrapAt);
			return outputStream.toString();
		} catch (IOException e) {
			BizLogger.error(e);
		}
		return "";
	}

	public static byte[] decode(byte[] bytes)  {
		try(
				ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
				ByteArrayOutputStream outputStream = new ByteArrayOutputStream()
        ) {

			decode(inputStream, outputStream);
			return outputStream.toByteArray();
		} catch (IOException e) {
			throw new BizException("Unexpected I/O error");
		}
	}

	public static void encode(InputStream inputStream, OutputStream outputStream)
			throws IOException {
		encode(inputStream, outputStream, 0);
	}

	public static void encode(InputStream inputStream,
			OutputStream outputStream, int wrapAt) throws IOException {
		Base64OutputStream aux = new Base64OutputStream(outputStream, wrapAt);
		copy(inputStream, aux);
		aux.commit();
	}

	public static void decode(InputStream inputStream, OutputStream outputStream)
			throws IOException {
		copy(new Base64InputStream(inputStream), outputStream);
	}

	public static void encode(File source, File target, int wrapAt) {
		try (
				InputStream inputStream = new FileInputStream(source);
				OutputStream outputStream = new FileOutputStream(target)
        ){

			encode(inputStream, outputStream, wrapAt);
		} catch (Exception e){
			BizLogger.error(e);
		}
	}

	public static void encode(File source, File target)  {
		try (
				InputStream	inputStream = new FileInputStream(source);
				OutputStream outputStream = new FileOutputStream(target)
        ){
			encode(inputStream, outputStream);
		}catch(Exception e){
			BizLogger.error(e);
		}
	}

	public static void decode(File source, File target) {
		try(
				InputStream inputStream = new FileInputStream(source);
			    OutputStream outputStream =new FileOutputStream(target)
        )
		 {
			decode(inputStream, outputStream);
		}catch (Exception e){
			BizLogger.error(e);
		}
	}

	private static void copy(InputStream inputStream, OutputStream outputStream)
			throws IOException {
		byte[] b = new byte[1024];
		int len;
		while ((len = inputStream.read(b)) != -1)
			outputStream.write(b, 0, len);
	}
}
